package com.sunwoda.springbootredis.service.impl;

import com.sunwoda.springbootredis.entity.User;
import com.sunwoda.springbootredis.dao.UserDao;
import com.sunwoda.springbootredis.enumcode.ResultCode;
import com.sunwoda.springbootredis.redislock.impl.RedisLockImpl;
import com.sunwoda.springbootredis.redislock.impl.RedisLockImpl2;
import com.sunwoda.springbootredis.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.DataType;
import org.springframework.data.redis.core.BoundValueOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * (User)表服务实现类
 *
 * @author makejava
 * @since 2021-09-11 08:45:49
 */
@Service("userService")
@Slf4j
public class UserServiceImpl implements UserService {
    @Resource
    private UserDao userDao;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public User queryById(Long id) {
        log.info(ResultCode.SUCCESS.getCode()+"");
        User user = this.userDao.queryById(id);
//        stringRedisTemplate.opsForValue().set("name",user.getName());
//        String name = stringRedisTemplate.opsForValue().get("name");
//        log.info(name);
        return user;
    }

    /**
     * 查询多条数据
     *
     * @param offset 查询起始位置
     * @param limit 查询条数
     * @return 对象列表
     */
    @Override
    public List<User> queryAllByLimit(int offset, int limit) {
        return this.userDao.queryAllByLimit(offset, limit);
    }

    /**
     * 新增数据
     *
     * @param user 实例对象
     * @return 实例对象
     */
    @Override
    public User insert(User user) {
        this.userDao.insert(user);
        return user;
    }

    /**
     * 修改数据
     *
     * @param user 实例对象
     * @return 实例对象
     */
    @Override
    public int update(User user) {
        String key = "lock";
        RedisLockImpl lock = new RedisLockImpl();
        boolean b = lock.tryLock(key, 1, TimeUnit.MILLISECONDS);
        if (!b){
            log.info("其他用户正在update");
            return -1;
        }
        int update = this.userDao.update(user);
        lock.releaseLock(key);
        return 1;
    }

    @Override
    public User update2(User user) {
        String key = "lock";
        RedisLockImpl2 lock = new RedisLockImpl2();
        String id = String.valueOf(Thread.currentThread().getId());
        boolean b = lock.tryLock(key,id, 60, TimeUnit.SECONDS);
        if (!b){
            log.info("其他用户正在update");
            return null;
        }
        this.userDao.update(user);
        lock.releaseLock(key,id);
        return this.queryById(user.getId());
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    @Override
    public boolean deleteById(Long id) {
        return this.userDao.deleteById(id) > 0;
    }

    @Override
    public List<User> getList(User re) {
        List<User> list = this.userDao.queryAll(re);
        list.forEach(one -> {
//            存储
            stringRedisTemplate.opsForValue().set(one.getName(),one.getName());
//            取值
            String s = stringRedisTemplate.opsForValue().get(one.getName());
            log.info(s);
        });
        return list;
    }

    @Override
    public void opsKey() {
        List<User> list = this.userDao.queryAll(new User());
        list.forEach(one -> {
//            获取所有键
            Set<String> keys = stringRedisTemplate.keys("*");
            keys.forEach(key -> {
                log.info(key);
            });
//            判断是否有键
            Boolean aBoolean = stringRedisTemplate.hasKey(one.getName());
            log.info(aBoolean.toString());
//            判断键的数据类型
            DataType type = stringRedisTemplate.type(one.getName());
            log.info(type.toString());
//            删除键
            Boolean delete = stringRedisTemplate.delete(one.getName());
            log.info(delete.toString());
        });
    }

    @Override
    public void opsDate() {
        //        修改键的序列化方案为String的序列化方案，这样在Redis中存储的键是String，而不是序列化后的值
        redisTemplate.setKeySerializer(new StringRedisSerializer());
//        修改hash的键序列化方案，因为在存储hash的时候有两个键
        List<User> list = this.userDao.queryAll(new User());
//        操作list
        redisTemplate.opsForList().leftPush("userList",list);

//        操作String
        redisTemplate.opsForValue().set("name",CollectionUtils.isEmpty(list)? "":list.get(0).getName());

//        操作set
        redisTemplate.opsForSet().add("userSet",list);

//        操作中Zset
        redisTemplate.opsForZSet().add("Zset",list,10);

//        操作hash
        redisTemplate.opsForHash().put("Hash","list",list);
    }

    @Override
    public void getAll() {
        List<User> list = this.userDao.queryAll(new User());
        StringBuffer stringBuffer = new StringBuffer();
        list.forEach(one -> {
            stringBuffer.append(one+"||");
        });
        log.info(stringBuffer+"");
        Iterator<User> iterator = list.iterator();
        while (iterator.hasNext()){
            User user = iterator.next();
            if (user.getId() == 1){
                iterator.remove();
            }
        }
        StringBuffer stringBuffer2 = new StringBuffer();
        list.forEach(one -> {
            stringBuffer2.append(one+"||");
        });
        log.info(stringBuffer2+"");

    }

    /**
     * @description: 绑定键
     * @param:
     * @return:
     * @author shiguorang
     * @date: 2021/9/12 11:26
     */
    @Override
    public void bound() {

        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());

        redisTemplate.opsForValue().set("name","shiguorang");
        redisTemplate.opsForValue().append("name","是一个好人");
        Object name1 = redisTemplate.opsForValue().get("name");
        log.info(name1.toString());

        BoundValueOperations name = redisTemplate.boundValueOps("name");
        name.set("lisi");
        log.info(name.get().toString());

    }

    @Override
    public User queryOne(User re) {
        return this.userDao.queryOne(re);
    }
}